package com.walterlife.base;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.Pipe;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;

class TestReflection {

    private int a;
    public int b;

    public TestReflection() {
        System.out.println("constructor none params");
    } 

    public TestReflection(int a) {
        this.a = a;
        System.out.println("constructor one params");
    } 

    public TestReflection(int a, int b) {
        this.a = a;
        this.b = b;
        System.out.println("constructor two params");
    } 
    
    public String toString() {
        return "TestReflection-a: " + this.a 
            + "\tTestReflection-b: " + this.b;
    } 

} 
public class App {

    public static void main(String[] args) throws IOException, NoSuchMethodException, SecurityException,
            InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        //testNIO();
        //testScatterAndGather();
        //testTransfer();
        //testSocket();
        //testPipe();
        testReflection();
    }
    
    public static void testReflection() throws NoSuchMethodException, SecurityException, InstantiationException,
            IllegalAccessException, IllegalArgumentException, InvocationTargetException {

        Class<TestReflection> aClass = TestReflection.class;
        String className = aClass.getName();
        String classSimpleName = aClass.getSimpleName();
        System.out.println(className);
        System.out.println(classSimpleName);

        int modifiers = aClass.getModifiers();
        System.out.println(Modifier.isPrivate(modifiers));

        //Constructor[] constructors = aClass.getConstructors(new Class[] {Integer.class});
        // 获得 参数个数为1个，参数类型为int 的构造函数
        Constructor<?> constructor = aClass.getConstructor(int.class);
        TestReflection object = (TestReflection)constructor.newInstance(1);
        System.out.println(object.toString());
    } 

    public static void testPipe() throws IOException {
        ByteBuffer buff = ByteBuffer.allocate(32);
        ByteBuffer tmpBuff = ByteBuffer.allocate(32);

        buff.put("Hello World".getBytes("utf-8"));
        
        Pipe pipe = Pipe.open();
        
        Pipe.SinkChannel sinkChannel = pipe.sink();
        buff.flip();
        while(buff.hasRemaining()) {
            sinkChannel.write(buff);
        } 
        
        tmpBuff.clear();
        int readLen = pipe.source().read(tmpBuff);

        if(readLen != -1) {
            System.out.println(new String(tmpBuff.array(), "utf-8"));

            //tmpBuff.flip();
            //System.out.println(new String(tmp, "utf-8"));
            //while(tmpBuff.hasRemaining()) {
                //System.out.println((char)tmpBuff.get());
            //}
        } 
    } 
    public static void testSocket() throws IOException {
        Selector selector = Selector.open();

        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.socket().bind(new InetSocketAddress(9999));
        
        serverSocketChannel.configureBlocking(false);

        // channel 必须是非阻塞的, OP_READ OP_ACCEPT OP_CONNECT OP_WRITE
        // 捕获的事件是可以 或的[add]
        // int integerSet = Selectionkey.OP_READ | Selectionkey.OP_WRITE
        SelectionKey key = serverSocketChannel.register(selector, SelectionKey.OP_READ);

        Thread connThrad = new Thread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub

            }
        });

        connThrad.setDaemon(true);
        connThrad.start();

        while(true) {
            SocketChannel socketChannel = 
                serverSocketChannel.accept();

            // do something
        } 
    } 
    public static void testSelect() throws IOException {
        Selector selector = Selector.open();
        RandomAccessFile fromFile = new RandomAccessFile("./file/from.txt", "rw");
        FileChannel fromChannel = fromFile.getChannel();
        
        //fromChannel.register(selector, SelectionKey.OP_READ);
        
    } 

    public static void testTransfer() throws FileNotFoundException {
        RandomAccessFile fromFile = new RandomAccessFile("./file/from.txt", "r");
        FileChannel fromChannel = fromFile.getChannel();

        RandomAccessFile toFile = new RandomAccessFile("./file/to.txt", "rw");
        FileChannel toChannel = toFile.getChannel(); 

        int position = 0;
        long size;
        try {
            size = fromChannel.size();
            // 将fromFile 的内容 拷贝到 toFile文件中
            toChannel.transferFrom(fromChannel, position, size);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();

        } finally {
            try {
                fromFile.close();
                toFile.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } 

    } 
    public static void testScatterAndGather() throws FileNotFoundException {
        RandomAccessFile file = new RandomAccessFile("./file/test.txt", "rw");
        FileChannel inChannel = file.getChannel();
        
        ByteBuffer bufFirst = ByteBuffer.allocate(10);
        ByteBuffer bufSec = ByteBuffer.allocate(10);
        
        bufFirst.put("dsdss".getBytes());
        bufSec.put("ewwwr".getBytes());

        ByteBuffer[] buffArray = { bufFirst, bufSec };

        try {
            // 分散读，将file channel 中的内容读到不同的buff 减少系统调用吧???
            //inChannel.read(buffArray);
            
            // 在读一个 Bytebuffer 之前must call flip
            bufFirst.flip();
            bufSec.flip();

            // 将各个buff 的内容写到 file channel中
            inChannel.write(buffArray);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
                file.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } finally {
                try {
                    file.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            } 
        } 

        bufFirst.flip();
        while(bufFirst.hasRemaining()) {
            System.out.println((char)bufFirst.get());
        } 
        System.out.println("------------------------");
        bufSec.flip();
        while(bufSec.hasRemaining()) {
            System.out.println((char)bufSec.get());
        } 
    } 

    public static void testNIO() throws FileNotFoundException {
        RandomAccessFile file = new RandomAccessFile("./test.txt", "rw");
        FileChannel inChannel = file.getChannel();

        ByteBuffer buf = ByteBuffer.allocate(48);

        int byteRead;
        try {
            byteRead = inChannel.read(buf);

            while(byteRead != -1) {
                // switch mode to readable
                // relative opreation: compact clear mark reset rewind 
                buf.flip();
                buf.compact();
                
                while(buf.hasRemaining()) {
                    System.out.println((char)buf.get());
                } 
                
                // switch mode to writeable
                buf.clear();
                // write data from channel into buffer
                byteRead = inChannel.read(buf);
            } 

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
                file.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } 
    } 
}
